package com.soup.hummingbird.module.jvm;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.List;

/**
 * 〈获取JVM内存和GC信息〉<br>
 *
 * @author zhaoyi
 * @date 2021-04-06 20:19
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Slf4j
public class JvmMetricCollect {
    private static final long MB = 1048576L;

    /**
     * 获取jvm内存信息
     */
    public static void memoryInfo() {
        MemoryMXBean memory = ManagementFactory.getMemoryMXBean();

        // 堆空间使用情况
        MemoryUsage heapMemory = memory.getHeapMemoryUsage();
        MemoryMetric heapMetric = new MemoryMetric();
        heapMetric.setInitSize(heapMemory.getInit() / MB);
        heapMetric.setMaxSize(heapMemory.getMax() / MB);
        heapMetric.setUsedSize(heapMemory.getUsed() / MB);
        heapMetric.setCommittedSize(heapMemory.getCommitted() / MB);
        heapMetric.setUsedRate(heapMemory.getUsed() * 100 / heapMemory.getCommitted());
        log.info("heapMetric: {}", heapMetric);

        // 非堆空间使用情况
        MemoryUsage nonHeapMemory = memory.getNonHeapMemoryUsage();
        MemoryMetric nonHeapMetric = new MemoryMetric();
        nonHeapMetric.setInitSize(nonHeapMemory.getInit() / MB);
        nonHeapMetric.setMaxSize(nonHeapMemory.getMax() / MB);
        nonHeapMetric.setUsedSize(nonHeapMemory.getUsed() / MB);
        nonHeapMetric.setCommittedSize(nonHeapMemory.getCommitted() / MB);
        nonHeapMetric.setUsedRate(nonHeapMemory.getUsed() * 100 / nonHeapMemory.getCommitted());
        log.info("nonHeapMetric: {}", nonHeapMetric);
    }

    /**
     * 获取GC信息
     */
    public static void gcInfo() {
        List<GarbageCollectorMXBean> garbageList = ManagementFactory.getGarbageCollectorMXBeans();
        for (GarbageCollectorMXBean garbage : garbageList) {
            GCMetric gcMetric = new GCMetric();
            gcMetric.setGcName(garbage.getName());
            gcMetric.setCollectCount(garbage.getCollectionCount());
            gcMetric.setCost(garbage.getCollectionTime());
            gcMetric.setMemoryPoolNames(garbage.getMemoryPoolNames());
            log.info("gcMetric: {}", gcMetric);
        }
    }

    /**
     * 内存使用信息
     */
    @Data
    public static class MemoryMetric {
        // 统计时间
        private long time = System.nanoTime();
        // 初始大小，单位MB
        private long initSize;
        // 最大，单位MB
        private long maxSize;
        // 已使用
        private long usedSize;
        // 已提交大小
        private long committedSize;
        // 使用率
        private float usedRate;
    }

    /**
     * GC信息
     */
    @Data
    public static class GCMetric {
        // 统计时间
        private long time = System.nanoTime();
        // 垃圾收集器名称
        private String gcName;
        // 收集次数
        private long collectCount;
        // 耗费时间，单位毫秒
        private long cost;
        private String[] memoryPoolNames;
    }

    public static void main(String[] args) {
        memoryInfo();
        gcInfo();
    }
}
